typespec1-6 Exercise 2: A Shop From the House Style =========================================================== shop.tsp (imports ../house/house.tsp from this chapter): import "@typespec/http"; import "../house/house.tsp"; using Http; using Acme.House; @service(#{ title: "Shop API" }) namespace Shop; /** Something for sale. */ model Product { @visibility(Lifecycle.Read) id: string; name: string; } @route("/products") interface Products { list is ListOf; @route("{id}") read is ReadOf; create is CreateOf>; @route("{id}") remove is DeleteOf; } The operations table: operation inputs responses GET /products query:limit, query:after 200, default POST /products BODY 201, 400, default GET /products/{id} path:id 200, 404, default DELETE /products/{id} path:id 204, 404, default house_check.py on it: 0 problem(s) With one hand-written operation added after the delete: @route("search") @get search(@query q: string): Product[]; The table now has an extra row: operation inputs responses GET /products query:limit, query:after 200, default POST /products BODY 201, 400, default GET /products/search query:q 200 GET /products/{id} path:id 200, 404, default DELETE /products/{id} path:id 204, 404, default house_check.py again: GET /products/search: no default response using ApiError GET /products/search: collection GET lacks limit/after 2 problem(s) WHICH RULES IT BREAKS, AND THE FIX No default response using ApiError: the operation says it can only answer 200. Add | Failure (the house alias for ApiError) to the return type. Collection GET lacks limit/after: it has q and nothing else, and returns a bare array. If search can return many results it needs limit and after and should return Page; if it genuinely returns a handful, the rule is wrong for it, and the check (which identifies a collection only by its path) cannot tell. A better fix (written but NOT compiled here) is a house template: op SearchOf(@query q: string, @query limit?: int32 = 20, @query after?: string): Page | Failure. Then search is written the same way as the other operations, and no service has to remember the rules. A note on the first run: the Shop built entirely from templates had 0 problems. That is not luck: the template's return type contains the 404 and the ApiError, so the service cannot forget them. WHY THIS WORKS AS AN ANSWER --------------------------- The exercise shows both halves of the chapter's argument: templates make consistency free for what they cover, and a script catches what someone writes outside them.