typespec1-4 Exercise 1: A Member Service =============================================== members.tsp (TypeSpec 1.17.0; OpenAPI 3.1.0): import "@typespec/http"; using Http; @service(#{ title: "Member Service" }) @server("https://api.example.com", "Production") namespace MemberService; model NewMember { name: string; email: string; } model Member { id: string; ...NewMember; } @error model NotFound { @statusCode _: 404; message: string; } @error model BadRequest { @statusCode _: 400; message: string; } model Created { @statusCode _: 201; @header location: string; @body body: T; } @route("/members") interface Members { @get list(@query limit?: int32 = 25, @query offset?: int32 = 0): Member[]; @route("{id}") @get read(@path id: string): Member | NotFound; @post create(@body member: NewMember): Created | BadRequest; @route("{id}") @delete remove(@path id: string): NoContentResponse | NotFound; } The operations table (from ops_table.py, which reads the generated OpenAPI JSON): operation inputs responses GET /members query:limit, query:offset 200 POST /members BODY 201, 400 GET /members/{id} path:id 200, 404 DELETE /members/{id} path:id 204, 404 CHECKING EACH OPERATION AGAINST THE BRIEF list GET /members: query parameters limit and offset (defaults 25 and 0), no body, 200. Good. read GET /members/{id}: path parameter, 200 and 404. Good. create POST /members: a body, and 201 and 400. The 201 carries the required location header (the Created template, written in the chapter's Book Service). Good. delete DELETE /members/{id}: 204 (NoContentResponse) and 404. Good. Things to notice: there is no 'default' response here because I did not write a generic @error model; every response a client can rely on is named. That is a choice: a client has no documented behaviour for, say, a 500. The Book Service's default ApiError is how chapter 4 handles it. WHY THIS WORKS AS AN ANSWER --------------------------- Every parameter is decorated, every verb and route is written, and every status code is chosen. The table is the review: it shows at a glance that no operation has an accidental body, and that creation answers 201 rather than the 200 that POST would have given by default.