mirror of
https://github.com/zap-proto/zip.git
synced 2026-10-19 15:38:57 +00:00
A typed op could only take one JSON value and answer one, so uploads, signed webhooks, form posts, YAML and merge-patch bodies, PDFs, SSE, WebSockets, OAuth redirects and upstream relays stayed untyped routes with no schema, tool, command or SDK method. Each is now a typed op and its REST wire is unchanged. Requests: a zip.Body field takes the body and Content-Type exactly as sent; an In implementing Parser decodes itself; form: fields and *zip.File parts bind url-encoded and multipart forms; cookie: binds a request cookie as an in: cookie parameter. Consumes names the media. Answers: zip.Body (bytes, filename, its own status and headers, a Reader streams chunked), Verbatim[T] (a relay documented as T), Sse[T] (events with keep-alive), Socket[M] (an upgrade after the contract runs; 426 without one, 501 over ZAP), Redirect, CookieCoder, Produces, and unions: a type whose OneOf method's results are the alternatives, with Or[A,B] as the stock one filing each under the status it states. Projections follow from the manifest: the document publishes binary media, form schemas, x-events, x-socket with 101, 3xx with Location and oneOf; MCP takes bytes as base64 and returns bytes, text or collected events as tool content, listing a socket op in _meta as no tool; the CLI reads --body @file|-, --field name=@file and --out, prints events as they arrive and bridges a socket to stdin and stdout. tools/list is ProjectMCP over the manifest, the projection MCPTools already was. Prose reaches promoted fields (filed under the declaring struct), a type defined over another struct, and the type arguments of zip's kinds and OneOf results; an instantiated generic is published under its name followed by its argument names instead of an illegal component key. The unused reflect-only document and tool builders go.
46 lines
1.1 KiB
Go
46 lines
1.1 KiB
Go
// Package generic answers through an instantiated generic, whose fields are
|
|
// documented once on the generic and filed under each instantiation's name.
|
|
package generic
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/zap-proto/zip"
|
|
)
|
|
|
|
// Envelope is the answer every op here wraps its data in.
|
|
type Envelope[T any] struct {
|
|
// Status is ok or error.
|
|
Status string `json:"status"`
|
|
// Data is what the op answers.
|
|
Data T `json:"data"`
|
|
}
|
|
|
|
// Store is one store.
|
|
type Store struct {
|
|
// Name is the store's name.
|
|
Name string `json:"name"`
|
|
}
|
|
|
|
// ListIn asks for stores.
|
|
type ListIn struct {
|
|
// Owner is the org whose stores are listed.
|
|
Owner string `json:"owner" url:"owner"`
|
|
}
|
|
|
|
// List returns the owner's stores.
|
|
func List(ctx context.Context, in *ListIn) (*Envelope[[]Store], error) {
|
|
return &Envelope[[]Store]{Status: "ok"}, nil
|
|
}
|
|
|
|
// One returns one store.
|
|
func One(ctx context.Context, in *ListIn) (*Envelope[Store], error) {
|
|
return &Envelope[Store]{Status: "ok"}, nil
|
|
}
|
|
|
|
// Register declares the ops.
|
|
func Register(app *zip.App) {
|
|
app.Get("/v1/stores/:owner", List)
|
|
app.Get("/v1/store/:owner", One)
|
|
}
|